package top.wshape1.shiziapi.uaa.controller;

import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.util.Base64Utils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import top.wshape1.shiziapi.common.constant.AuthConstant;
import top.wshape1.shiziapi.common.constant.BizCodeEnum;
import top.wshape1.shiziapi.common.domain.vo.PageVo;
import top.wshape1.shiziapi.common.group.uaa.RegGroup;
import top.wshape1.shiziapi.common.utils.R;
import top.wshape1.shiziapi.uaa.domain.User;
import top.wshape1.shiziapi.uaa.domain.vo.InfoVo;
import top.wshape1.shiziapi.uaa.domain.vo.MemberVo;
import top.wshape1.shiziapi.uaa.domain.vo.PasswordVo;
import top.wshape1.shiziapi.uaa.domain.vo.UserLoginVo;
import top.wshape1.shiziapi.uaa.service.JwtService;
import top.wshape1.shiziapi.uaa.service.UserService;

import java.util.Collection;

/**
 * @author Wshape1
 * @version 1.0
 * @description
 * @since 2023-08-26
 */

@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    @Resource
    private JwtService jwtService;

    /**
     * 获取token里面的user信息
     *
     * @param userEncoded
     * @return
     */
    @GetMapping("/_")
    public R<User> getUserFromToken(@RequestHeader(AuthConstant.HEADER_PAYLOAD_NAME) String userEncoded) {

        User user = userService.getFromEncodedString(userEncoded);

        return R.ok().putData(user);
    }

    /**
     * 修改密码
     *
     * @param passwordVo
     * @param userEncoded
     * @return
     */
    @PostMapping("/password")
    public R<Void> modifyPassword(@RequestBody @Validated PasswordVo passwordVo,
                                  @RequestHeader(AuthConstant.HEADER_PAYLOAD_NAME) String userEncoded) {
        User user = userService.getFromEncodedString(userEncoded);
        userService.modifyPassword(user, passwordVo);
        return R.ok();
    }

    /**
     * 发送绑定邮箱的验证码
     *
     * @param userEncoded
     * @param emailBase64
     * @return
     */
    @PostMapping("/binding/code")
    public R<Void> sendBindingCode(@RequestHeader(AuthConstant.HEADER_PAYLOAD_NAME) String userEncoded,
                                   @RequestParam("email") String emailBase64) {

        String email = new String(Base64Utils.decodeFromString(emailBase64));

        if (!email.matches("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$")) {
            return R.instance(BizCodeEnum.INVALID_DATA_ERROR.code(), BizCodeEnum.INVALID_DATA_ERROR.msg());
        }

        User user = userService.getFromEncodedString(userEncoded);

        userService.sendBindingCode(user, email);

        return R.ok();
    }

    /**
     * 绑定邮箱
     *
     * @param userLoginVo
     * @param userEncoded
     * @param oldToken
     * @param response
     * @return
     */
    @PostMapping("/binding")
    public R<Void> bindingEmail(@RequestBody @Validated(RegGroup.class) UserLoginVo userLoginVo,
                                @RequestHeader(AuthConstant.HEADER_PAYLOAD_NAME) String userEncoded,
                                @RequestHeader(HttpHeaders.AUTHORIZATION) String oldToken,
                                HttpServletResponse response) {
        User user = userService.getFromEncodedString(userEncoded);
        // 绑定邮箱
        userService.bindingEmail(user, userLoginVo.getEmail(), userLoginVo.getPassword(), userLoginVo.getCode());

        oldToken = oldToken.replace("Bearer ", "");
        // 更新token
        jwtService.setNewToken(user.getId(), oldToken, response);

        return R.ok();
    }


    /**
     * 解绑 邮箱、Gitee或Github
     *
     * @param type
     * @param userEncoded
     * @param oldToken
     * @param response
     * @return
     */
    @PostMapping("/unbinding/{type}")
    public R<Void> unbinding(@PathVariable("type") String type,
                             @RequestHeader(AuthConstant.HEADER_PAYLOAD_NAME) String userEncoded,
                             @RequestHeader(HttpHeaders.AUTHORIZATION) String oldToken,
                             HttpServletResponse response) {

        oldToken = oldToken.replace("Bearer ", "");

        User user = userService.getFromEncodedString(userEncoded);

        userService.unbinding(user, type);

        jwtService.setNewToken(user.getId(), oldToken, response);

        return R.ok();
    }

    @PostMapping("/info")
    public R<Void> modifyInfo(@Validated InfoVo infoVo,
                              @RequestParam(value = "file", required = false) MultipartFile file,
                              @RequestHeader(AuthConstant.HEADER_PAYLOAD_NAME) String userEncoded,
                              @RequestHeader(HttpHeaders.AUTHORIZATION) String oldToken,
                              HttpServletResponse response) {


        oldToken = oldToken.replace("Bearer ", "");

        User user = userService.getFromEncodedString(userEncoded);

        if (userService.modifyInfo(user, infoVo, file)) {
            jwtService.setNewToken(user.getId(), oldToken, response);
        }


        return R.ok();
    }


    @PostMapping("/memberPage")
    public R<PageVo> getMemberPage(@RequestParam(value = "page", required = false, defaultValue = "1") Long page,
                                   @RequestParam(value = "limit", required = false, defaultValue = "6") Long limit,
                                   @RequestBody Collection<Long> userIds) {

        PageVo pageVo = userService.getMemberPage(page, limit, userIds);

        return R.ok(pageVo);
    }

    @GetMapping("/member")
    public R<MemberVo> getMemberById(@RequestParam("id") Long id) {
        MemberVo member = userService.getMemberById(id);
        return R.ok(member);
    }

    @GetMapping("/name")
    public R<String> getNameById(@RequestParam("id") Long id) {
        User user = userService.getById(id);
        if (user != null) {
            return R.ok().putData(user.getNickname());
        }
        return R.error();
    }


}
